package com.demo.project_template.base.im.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.demo.project_template.base.im.entity.Message;
import com.demo.project_template.base.im.entity.SysNotice;
import com.demo.project_template.base.im.service.YxService;
import com.demo.project_template.base.im.utils.CheckSumBuilder;
import com.demo.project_template.exception.ErrorCodeException;
import okhttp3.*;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
public class YxServiceImpl implements YxService {

    private static final String APP_KEY = "698bc03d5a0f1dac5667941e83b0e951";

    private static final OkHttpClient client = new OkHttpClient();

    /**
     * 注册云信IM账号
     * @param accountId 云信账号id（需保证唯一性） 本系统采用的是用户手机号
     * @return 云信token，不主动调用云信的刷新方法可以一直有效
     */
    @Override
    public String register(String accountId) {
        String url = "https://open.yunxinapi.com/im/v2/accounts";
        Map<String, String> bodies = new HashMap<>();
        bodies.put("account_id", accountId);
        JSONObject response = callApi(url, JSON.toJSONString(bodies));
        return response.getJSONObject("data").getString("token");
    }

    /**
     *
     * 发送单聊消息
     * @param senderId 发送者account_id
     * @param receiverId 接收者account_id
     * @param message 消息对象
     * @return 是否发送成功
     */
    public Boolean sendMessage(String senderId, String receiverId, Message message){
        String url = "https://open.yunxinapi.com/im/v2/conversations/"+senderId+"|1|"+receiverId+"/messages";
        Map<String, String> bodies = new HashMap<>();
        bodies.put("message", JSON.toJSONString(message));
        JSONObject response = callApi(url, JSON.toJSONString(bodies));
        return response.getInteger("code")==200;
    }

    /**
     * 发送单聊系统通知
     * @param sysNotice 通知对象
     * @return 是否发送成功
     */
    public Boolean sendSysNotice(SysNotice sysNotice){
        String url = "https://open.yunxinapi.com/im/v2/custom_notification";
        JSONObject response = callApi(url, JSON.toJSONString(sysNotice));
        return response.getInteger("code")==200;
    }

    /**
     * 订阅用户在线状态事件
     * @param accountId 订阅者account_id
     * @param accountIds 发布在线状态事件的用户账号列表。单次最多操作 100 个账号
     */
    public Boolean queryUserOnline(String accountId,String[] accountIds){
        String url = "https://open.yunxinapi.com/im/v2/subscription/"+accountId+"?duration="+2592000L;
        Map<String, String> bodies = new HashMap<>();
        bodies.put("account_ids", JSON.toJSONString(accountIds));
        JSONObject response = callApi(url, JSON.toJSONString(bodies));
        return response.getInteger("code")==200;
    }

    /**
     * 获取请求头
     * @return 请求头
     */
    private Map<String,String> getHeader(){
        String nonce = UUID.randomUUID().toString();
        String curTime = String.valueOf(new Date().getTime() / 1000);
        String checkSum = CheckSumBuilder.getCheckSum(nonce, curTime);
        Map<String, String> headers = new HashMap<>();
        headers.put("AppKey", APP_KEY);
        headers.put("Nonce", nonce);
        headers.put("CurTime", curTime);
        headers.put("CheckSum", checkSum);
        return headers;
    }

    /**
     * 发起API调用
     * @param url api地址
     * @param requestBody 请求体
     * @return 响应对象
     */
    private JSONObject callApi(String url, String requestBody) {
        // 构建请求体
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody);

        // 构建请求
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
                .post(body);

        // 添加请求头
        Map<String, String> headers = getHeader();
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            requestBuilder.addHeader(entry.getKey(), entry.getValue());
        }

        Request request = requestBuilder.build();

        // 执行请求
        try (Response response = client.newCall(request).execute()) {
            if (response.body() == null || !response.isSuccessful()) {
                throw new ErrorCodeException("Unexpected code " + response);
            }
            return JSON.parseObject(response.body().toString());
        } catch (IOException e) {
            throw new ErrorCodeException(e.getMessage());
        }
    }
}
